package write.oo;

/**
 * 类是将一类事物上的部分属性抽象话
 * 例：a人10岁，b人8岁
 * 对类来说，就可以抽象（a,b）--name,(10,8)--age,
 * 现实生活是由很多很多对象组成的，基于对象抽出了类
 * 对象：软件中真实存在的单个的个体/东西
 * 类：类型/类别，代表一类个体
 * 类是对象的模子/模板，对象是类的具体的实例，可以将类理解为类别/模子/图纸
 *
 * 类可以创建无限个对象
 */

//类的访问控制权限只有public和默认的(不写)
//public是访问控制权限 class是定义类的关键字
public class Person {

    /**类成员(属性，方法，内部类)的访问控制权限有：
     *      public :      公开的       任何类
     *      protected :   受保护的     本类、同包类、子类
     *      默认的(不写) :  默认的      本类、同包类
     *      private:      私有的      本类
     */
    //类的成员变量，
    /** javaBean 要求成员全部私有化 */
    //对象的属性/特征/数据----------------------成员变量
    private String name;
    private int age;
    public static String race;

    /**
     * 执行顺序优先级：静态块>main()>构造块>构造方法
     * 并不是静态块最先初始化,而是静态域.(对，静态域)
     * 而静态域中包含静态变量、静态块和静态方法,其中需要初始化的是静态变量和静态块.
     * 而他们两个的初始化顺序是靠他们俩的位置决定的!
     */
    /** 静态块，只在类加载时执行，只执行一次
     * 一般用于加载静态资源
     */
    static{
        System.out.println("静态块执行");
        race = "人";
    }
    /** 构造块,每一次创建对象时执行 */
    {
        System.out.println("构造块执行");
        age = 5;
    }

    /** javaBean 必须提供一个无参构造器 */
    /**
     * 如果类内没有写构造器，java会默认提供一个无参的，
     *     但如果定义了，哪怕不是无参的，java也不再提供默认的
     *     作用：给成员变量赋初始值
     *     语法：与类同名，没有返回值类型(连void都没有)
     *     调用：在创建(new)对象时被自动调用
     *     可以重载
     */
    public Person() {
        System.out.println("无参构造执行");
    }
    //复用给成员变量赋初始值的代码
    /**
     *this:不可省略的情况
     * 形参名和成员变量名一致时(java允许这种情况)，根据就近原则，
     * 若此时省略this则指向的都是形参中的参数，无法正常使用成员变量，此时就不能省略this.
     *
     */
    public Person(String name, int age) {
        System.out.println("有参构造执行");
        this.name = name;
        this.age = age;
    }

    //对象的行为/动作/功能----------------------方法
    /**
     *  this：指代当前对象，哪个对象调用方法它指的就是哪个对象
     *  只能用在方法中，方法中访问成员变量之前默认有个this
     *
     *  this.成员变量名--------------------访问成员变量
     *  this.方法名()-------------------------调用方法
     *  this()----------------------------调用构造方法
     *
     *  this一般都可以省略
     */
    void say(){
        System.out.println(this.name);
        System.out.println(name);
        this.sayHi();
        sayHi();
    }
    void sayHi(){
        System.out.println(age);
    }

    void innerMethod(){
        //外部类访问内部类需要new对象调用
        new InternalClass().please();
    }


    /** javaBean提供私有属性对应的公开getter/setter方法 */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 成员内部类：
     * 类中套类，外面的称为外部类，里面的称为内部类
     * 内部类通常只服务于外部类，对外不具备可见性
     * 内部类对象通常在外部类中创建
     *
     * 内部类可以直接访问外部类的成员，在内部类中有个隐式的引用指向创建它的外部类对象
     * 隐式的引用：外部类名.this
     *
     * 何时用：若A类只让B类用，并且A类还想访问B类的成员时，可以设计成员内部类
     *
     * 成员内部类：两个身份，一个是“成员”，一个是“内部类”
     * 这让成员内部类可以被 四种访问控制权限 修饰，其他修饰符包括static...
     *
     *  内部类可以由外面访问，但需通过外部类跳转
     *  内部类非静态(无static修饰)
     *  Mama.Baby b = new Mama().new Baby();
     *  内部类静态(static修饰)
     *  Mama.Baby b = new Mama.Baby();
     */
    class InternalClass{
        void please(){
            //内部类可以直接访问外部类的成员，在内部类中有个隐式的引用指向创建它的外部类对象
            // 隐式的引用：外部类名.this
            System.out.println(age);
        }

    }
}
